<?php
/**
 * DBData 를 다루기 위한 파일
 * 
 * @package php.db
 */

/**
 * DB 관련 Data를 다루기 위한 클래스입니다.
 * 
 * <code>
 * $db = DB_('mssql', 'db', true);
 *
 * // 조건절 select 
 * $data->select(" datetime is not null order by 1", false, array('ab','bc','cde'));
 *
 * // 조건절 selectPage 
 * $page = 1;
 * $limitPage = 10;
 * $data->selectPage(" datetime is not null order by 1", $page, $limitPage, array('ab','bc','cde'));
 * 
 * // count 얻기 
 * $limitPage = 10;
 * $limitBlock = 10;
 * $arr = $data->selectCount(" datetime is not null ", $limitPage, $limitBlock);
 * 
 * //$arr['count'] : 전체개수 , $arr['page'] : 페이지 개수, $arr['block'] : 블럭개수
 *
 * 
 * $db->close();
 * </code> 
 * 
 * @package php.db
 * @todo ActiveRecord 패턴 도입 예정
 */
class DBData extends Data {

	/**
	 * 테이블 이름 
	 * @var string 
	 */
	protected $table;

	/**
	 * 데이타 타입 리스트 
	 *
	 * @var array 
	 */
	protected $types = array();


	/** 
	 * 생성자
	 *
	 * @param IConnector $connector 연결자 
	 * @param string $table 테이블 이름 
	 * @param string $where 조건절 
	 * @param string $field field리스트
	 */
	public function __construct($connector = null, $table = null, $where = null) {
		parent::__construct($connector);

		$this->setTable($table);

		if ($where) { 
			$this->select($where);
		}

	}
	
	public function getTypeString($type, $value, $is_null = false ) {
		return $this->getConnector()->getTypeString($type, $value, $is_null);
	}

	/**
	 * 테이블 이름 설정 
	 * 
	 * @param string $table 테이블이름 
	 */
	public function setTable($table) {
		$this->table = $table;
	}

	/**
	 * 테이블 이름을 얻어옵니다.
	 * 
	 * @return string 
	 */
	public function getTable() {
		return $this->table;
	}

	/**
	 * 타입 리스트 얻기 
	 * 
	 * @return array 타입 리스트를 배열로 얻어옵니다.
	 */
	public function getTypeList() { 
		return $this->types;
	}
	
	/**
	 * 타입 리스트를 설정합니다.
	 * 
	 * <code> $dbdata->setTypeList(array('field1' => 'varchar', ....)); </code>
	 * 
	 * @param array $arr 타입 리스트 
	 */
	public function setTypeList($arr) { 
		$this->types = array_change_key_case($arr, CASE_LOWER);
	}

	/** 
	 * 필드 값으로 검색한다. 
	 * 
	 * @return DBData 
	 */
	public function __call($method, $args = array()) {

		// ts 타입 메소드   
		if (strpos($method, "ts") === 0) { 
			$temp = explode("ts", $method);
			array_shift($temp);
			$str = implode("ts", $temp);
			
			$type = $str;
			$value = $this->get($args[0]);

			return $this->getTypeString($type, $value);
		}
		
		return parent::__call($method, $args);		
	}

	/**
	 * 검색쿼리 
	 *
	 * <code> echo $data->select(" a = '1' ", false, array('a', 'b', 'c'));  </code>
	 *
	 * @param string $where  조건절 
	 * @param bool $hasNext 한칸 전진 여부 
	 * @param array $field_list 얻어올 필드 리스트
	 * @return DBData  
	 */
	public function select($where = '', $hasNext = false, $field_list = array())
	{
		$connector = $this->getConnector();

		$sql = new Sql($connector->program, "select");
		$sql->setFrom($this->table);

		foreach ($field_list as $field) { 
			$sql->add($field);
		}

		$str = $sql->toString(). " ". (trim($where) == '' ? '' : ' where '. $where );

//		echo $str;

		$data = $connector->getData($str);

		$this->setData($data);

		if ($hasNext) $this->next();

		return $this;
	}

	/**
	 * 전체 데이타 불러오기 
	 *
	 * @return DBData
	 */
	public function loadAll() { 
		return $this->select(" 1 = 1");
	}

	/** 
	 * 페이징 검색 쿼리 
	 *
	 * <code> echo $data->selectPage(" a = '1' ", 1, 10, array('a', 'b', 'c'));  </code>
	 *
	 * @param string $where 조건절
	 * @param int $page 검색될 페이지 
	 * @param int $pagesize 한페이지당 레코드 개수 
	 * @param array $field_list 필드 리스트 
	 * @return DBData $this 
	 */
	public function selectPage($where = '', $page = 1 , $pagesize = 10, $field_list = array())
	{
		$connector = $this->getConnector();

		$sql = new Sql($connector->program, "select");
		$sql->setFrom($this->table);

		foreach ($field_list as $field) { 
			$sql->add($field);
		}

		$str = $sql->toString(). " ". (trim($where) == '' ? '' : ' where '. $where );

//		echo $str;

		$data = $connector->getPageData($str, $page, $pagesize);

		$this->setData($data);

		return $this;
	}

	/**
	 * 검색 갯수 얻어오기 
	 *
	 * @param string $where 조건문 
	 * @param int $pagesize 한 페이지당 나타낼 레코드 개수
	 * @param int $blocksize 한 블럭당 나타낼 페이지 개수 
	 * @return array    count : 전체개수, page : 페이지 개수, block : 블럭개수
	 * @see DBClient::getPageCountQuery()
	 */ 
	public function selectCount($where = '', $pagesize = 10, $blocksize = 10)
	{
		$connector = $this->getConnector();

		$sql = new Sql($connector->program, "select");
		$sql->setFrom($this->table);
		$sql->add('count(*) as cnt', '', false);

		$str = $sql->toString(). " ". (trim($where) == '' ? '' : ' where '. $where );

		return $connector->getPageCountQuery($str, $pagesize, $blocksize);
	}



	/**
	 * 현재 인덱스에 있는 데이타 delete 실행 
	 * 
	 * @return bool 쿼리 실행 여부 
	 */
	public function delete() {
		$connector = $this->getConnector();

		$tempSql = $connector->deleteSql($this);

		return $connector->query($tempSql->toString());
	}

	/**
	 * 현재 인덱스에 있는 데이타 update 실행 
	 * 
	 * @param array $omit 제한할 필드 리스트
	 * @param bool $is_update_field	false 제외할 필드, true 적용할 필드  	 
	 * @return bool 쿼리 실행 여부 
	 */
	public function update($omit = array(), $is_update_field = false) {
		$connector = $this->getConnector();

		$tempSql = $connector->updateSql($this, $omit, $is_update_field);

		return $connector->query($tempSql->toString());
	}

	/**
	 * 현재 인덱스에 있는 데이타 insert 실행 
	 *
	 * @param array $omit 제한할 필드 리스트 
	 * @return bool 쿼리 실행 여부 
	 */
	public function insert($omit = array()) {
		$connector = $this->getConnector();

		$tempSql = $connector->insertSql($this, $omit);

		return $connector->query($tempSql->toString()) or die("insert : ".$connector->error());
	}

	/**
	 * 현재 데이타 모두 insert 실행 
	 *
	 * @param array $omit 제한할 필드 리스트 	 
	 */
	public function insertAll($omit = array()) {
		$this->saveIndex();

		while($this->next()) 
			$this->insert($omit);

		$this->returnIndex();
	}

	/**
	 * 현재 데이타 모두 delete 실행 
	 * 
	 */
	public function deleteAll() {
		$this->saveIndex();

		while($this->next()) 
			$this->delete();

		$this->returnIndex();
	}

	/**
	 * 현재 데이타 모두 update 실행 
	 * 
	 * @param array $omit 제한할 필드 리스트 
	 */
	public function updateAll($omit = array()) {
		$this->saveIndex();

		while($this->next()) 
			$this->update($omit);

		$this->returnIndex();
	}

	/**
	 * 외부 데이타 들고 오기 
	 * 
	 * @param string $table 자식 테이블 이름 
	 * @param string $field1 자식 필드 
	 * @param string $field2 부모 필드 
	 * @param string $field_list 얻어올 필드 리스트 
	 * @return DBData 자식 테이블 DBData객체
	 * @deprecated
	 */
	public function getSubData($table, $field1, $field2, $field_list = '') { 
		$value = $this->get($field2);
		$field_list = (trim($field_list) == '') ? " * " : $field_list;
		$sql = "select {$field_list} from {$table} where $field = '{$value}'";

		return $this->getConnector()->getData($sql, $isOne);
	}
}
?>